package com.lhy.admin.common.secure.authorization;

import com.lhy.admin.Constants;
import com.lhy.admin.common.secure.SecureValidator;
import com.lhy.admin.common.secure.authentication.Authentication;
import com.lhy.admin.util.AnnotationUtil;
import com.lhy.admin.util.SpringContextUtil;
import org.springframework.util.StringUtils;
import org.springframework.web.method.HandlerMethod;

import javax.servlet.http.HttpServletRequest;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;

public class PermissionLogicalValidator implements SecureValidator {

    @Override
    public boolean validate(HandlerMethod handlerMethod, HttpServletRequest request) {
        Permissions permission = AnnotationUtil.getAnnotation(handlerMethod, Permissions.class);
        if (permission == null) {
            return true;
        }
        // 带Authentication注解请求无需权限校验
        Authentication authentication = AnnotationUtil.getAnnotation(handlerMethod, Authentication.class);
        if (authentication != null) {
            return true;
        }

        final String finalLogicName = getLogicName(permission);
        List<String> curRequestPermissions = Arrays.asList(permission.value());
        List<String> sessionPermissions = (List<String>) request.getSession().getAttribute(Constants.PERMISSIONS_CODE);

        PermissionLogicalStrategy logicalStrategy = getPermissionLogicalStrategy(finalLogicName);
        return logicalStrategy.authorization(sessionPermissions, curRequestPermissions, request);

    }

    private String getLogicName(Permissions permission) {
        Logical logical = permission.logical();
        String logicalName = permission.logicalName();
        final String finalLogicName;
        if (StringUtils.hasText(logicalName)) {
            finalLogicName = logicalName;
        } else {
            finalLogicName = logical.name();
        }
        return finalLogicName;
    }

    private PermissionLogicalStrategy getPermissionLogicalStrategy(final String finalLogicName) {
        Collection<PermissionLogicalStrategy> beans = SpringContextUtil.getBeans(PermissionLogicalStrategy.class);
        List<PermissionLogicalStrategy> permissionLogicalStrategies = beans.stream()
                .filter(permissionLogicalStrategy -> permissionLogicalStrategy.logicalName().equals(finalLogicName)).collect(Collectors.toList());
        if (permissionLogicalStrategies.isEmpty()) {
            throw new RuntimeException("can not found one permissionLogicalStrategy by logicName:" + finalLogicName);
        }
        if (permissionLogicalStrategies.size() > 1) {
            throw new RuntimeException("found multiple permissionLogicalStrategies by logicName:" + finalLogicName + ", but should found only one");
        }
        return permissionLogicalStrategies.get(0);
    }

}
